from functools import wraps
from dmq import ZMQResponse
from django.template import RequestContext
from django.shortcuts import render_to_response


class DMQInvalidRequest(Exception):
    """docstring for DMQInvalidRequest"""
    def __init__(self, *args):
        super(DMQInvalidRequest, self).__init__(*args)
#DMQInvalidRequest


class DMQInvalidResponse(Exception):
    """docstring for DMQInvalidResponse"""
    def __init__(self, *args):
        super(DMQInvalidResponse, self).__init__(*args)
#DMQInvalidResponse


def dmq_render_to(template=None, mimetype=None):
    """
    Decorator for Django views that sends returned dict to render_to_response
    function.

    Template name can be decorator parameter or TEMPLATE item in returned
    dictionary.  RequestContext always added as context instance.
    If view doesn't return dict then decorator simply returns output.

    Parameters:
        - template: template name to use
        - mimetype: content type to send in response headers

    Examples:
    # 1. Template name in decorator parameters

    @render_to('template.html')
    def foo(request):
        bar = Bar.object.all()
        return {'bar': bar}

    # equals to
    def foo(request):
        bar = Bar.object.all()
        return render_to_response('template.html',
                                {'bar': bar},
                                context_instance=RequestContext(request))

    # 2. Template name as TEMPLATE item value in return dictionary.
        if TEMPLATE is given then its value will have higher priority
        than render_to argument.

    @render_to()
    def foo(request, category):
        template_name = '%s.html' % category
        return {'bar': bar, 'TEMPLATE': template_name}

    #equals to
    def foo(request, category):
    template_name = '%s.html' % category
    return render_to_response(template_name,
                                {'bar': bar},
                                context_instance=RequestContext(request))
    """
    def renderer(function):

        @wraps(function)
        def wrapper(request, *args, **kwargs):

            output = function(request, *args, **kwargs)
            if request.__class__.__name__ == 'ZMQRequest':
                if not isinstance(output, dict):
                    # A ZMQResponse may have been crafted
                    # by the caller or the caller 'knows what they're doing',
                    # in which case we won't touch their output.
                    return output
                return ZMQResponse(request, output)

            if not isinstance(output, dict):
                return output
            tmpl = output.pop('TEMPLATE', template)
            return render_to_response(tmpl, output, \
                                      context_instance=RequestContext(request),
                                      mimetype=mimetype)
        return wrapper
    return renderer
#dmq_render_to()


def dmq_only(func):
    """
    Only allow ZMQRequest type of requests and only
    allow ZMQResponse return objects. Oh, and enforce it.
    """

    @wraps(func)
    def wrapper(request, *args, **kwargs):

        if request.__class__.__name__ == 'ZMQRequest':
            output = function(request, *args, **kwargs)
            if not isinstance(output, dict):
                # A ZMQResponse may have been crafted
                # by the caller
                if output.__class__.__name__ == 'ZMQResponse':
                    return output
                else:
                    raise DMQInvalidResponse(("The view was decorated with "
                                "@dmq_only, but returned a response that is"
                                "NOT an instance of ZMQResponse"))

            return ZMQResponse(request, output)

        raise DMQInvalidRequest(("This method is decorated with @dmq_only, "
                "but the request is not a ZMQRequest object"))
    return wrapper
#dmq_only()
